<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>6.使用噪声绘制纹理-噪声实现云雾效果</title>
    <style>
        canvas{
            border:1px solid #aaa;
            margin: 0 auto;
            display: block;
        }
    </style>
</head>
<body>
    <canvas width="554" height="554"></canvas>
    <script src="/common/lib/gl-renderer.js"></script>

    <script type="module">
        import { loadImage, toPolar, fromPolar } from "/common/lib/utils.js";
        
        /**
         * gl-renderer五步法
         * 1.创建renderer对象
         * 2.创建并启用webgl程序
         * 3.设置uniform变量
         * 4.将定点数据送入缓冲区
         * 5.渲染
         * 
        */
        // 1.
        let canvas = document.querySelector("canvas");
        const renderer = new GlRenderer(canvas);

        // 2.
        const vertex = `
            attribute vec2 a_vertexPosition;
            attribute vec2 uv;
            varying vec2 vUv;

            void main(){
                gl_PointSize = 1.0;
                vUv = uv;
                gl_Position = vec4(a_vertexPosition, 1.0, 1.0);
            }
        `
        // 
        const fragment = `
            #ifdef GL_ES
            precision highp float;
            #endif
            #define OCTAVES 6

            uniform float uTime;
            varying vec2 vUv;

            // 随机的二维向量
            vec2 random2(vec2 st){
                st = vec2(dot(st, vec2(127.1,311.7)), dot(st, vec2(269.5,183.3)));
                return -1.0 + 2.0 * fract(sin(st) * 43758.5453123);
            }

            // 梯度噪声生成方法
            float noise(vec2 st) {
                vec2 i = floor(st);
                vec2 f = fract(st);
                vec2 u = f * f * (3.0 - 2.0 * f);
                return mix( mix( dot( random2( i + vec2(0.0,0.0)), f - vec2(0.0,0.0) ), 
                                 dot( random2( i + vec2(1.0,0.0)), f - vec2(1.0,0.0) ), u.x),
                            mix( dot( random2( i + vec2(0.0,1.0)), f - vec2(0.0,1.0) ), 
                                 dot( random2( i + vec2(1.0,1.0)), f - vec2(1.0,1.0) ), u.x), u.y);
            }
            vec3 hsv2rgb(vec3 c){ 
                vec3 rgb = clamp(abs(mod(c.x*6.0+vec3(0.0,4.0,2.0), 6.0)-3.0)-1.0, 0.0, 1.0); 
                rgb = rgb * rgb * (3.0 - 2.0 * rgb); 
                return c.z * mix(vec3(1.0), rgb, c.y);
            }
            // 云雾叠加效果
            float mist(vec2 st){
                // 初始化值
                float value = 0.0;
                float amplitude = 0.5;
                // 叠加6次  
                for(int i = 0; i < OCTAVES; i++) {    
                    // 每次范围扩大一倍，权重减半    
                    value += amplitude * noise(st);    
                    st *= 2.0;    
                    amplitude *= 0.5;  
                }  
                return value;
            }

            //配合色相的变化
            void main() {
                vec2 st = vUv;
                st.x += 0.1 * uTime * 0.0005;
                gl_FragColor.rgb = hsv2rgb(vec3 (mist(st), 1.0, 1.0));
                gl_FragColor.a = 1.0;
            }
        `

        const program = renderer.compileSync(fragment,vertex)
        renderer.useProgram(program)
        // 3.
        renderer.uniforms.uTime = 0.0
        // 4.
        renderer.setMeshData([
            {
                positions:[
                    [-1,-1],
                    [-1,1],
                    [1,1],
                    [1,-1],
                ],
                attributes:{
                    uv:[
                        [0,0],
                        [0,1],
                        [1,1],
                        [1,0],
                    ]
                },
                cells:[[0,1,2],[2,0,3]]
            }
        ])
        // 5.
        renderer.render()

        function update(uTime){
            renderer.uniforms.uTime = uTime
            requestAnimationFrame(update)
        }

        update(0.0)

    </script>
</body>
</html>